package bw.gui;

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.swing.BoxLayout;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;

import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLAxiom;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLEquivalentClassesAxiom;
import org.semanticweb.owlapi.model.OWLIndividual;
import org.semanticweb.owlapi.model.OWLNamedIndividual;
import org.semanticweb.owlapi.model.OWLNegativeObjectPropertyAssertionAxiom;
import org.semanticweb.owlapi.model.OWLObjectOneOf;
import org.semanticweb.owlapi.model.OWLObjectProperty;
import org.semanticweb.owlapi.model.OWLObjectPropertyAssertionAxiom;
import org.semanticweb.owlapi.model.OWLObjectSomeValuesFrom;
import org.semanticweb.owlapi.model.OWLOntologyChange;

import bw.owl.Ontology;
import bw.owl.Pracownik;
import bw.owl.Umiejetnosc;
import bw.owl.Zadanie;

public class ZadaniaPanel extends JPanel implements ActionListener{

    private InstanceViewer parent;
    private GroupLayout layout;
    private JButton dodaj;
//    private JButton usun;
//    private JButton zmienNazwe;
    private JButton edytujPracownikow;
    private JButton edytujUmiejetnosci;
    private JList listaZadan;
    private JCheckBox czyWszystkie;

    public ZadaniaPanel(InstanceViewer viewer) {
	parent = viewer;
        layout = new GroupLayout(this);
        setLayout(layout);

        layout.setAutoCreateGaps(true);
        layout.setAutoCreateContainerGaps(true);

        listaZadan = new JList();
        JScrollPane scrollPane = new JScrollPane(listaZadan);
        scrollPane.setMinimumSize(new Dimension(600, 100));

        dodaj = new JButton("Dodaj");
//        usun = new JButton("Usuń");
//        zmienNazwe = new JButton("Zmień nazwę");
        edytujPracownikow = new JButton("Edytuj pracowników którzy wykonywali");
        edytujUmiejetnosci = new JButton("Edytuj wymagane Umiejętności");

        JLabel wszyscy = new JLabel("Czy wszystkie zadania są znane?");
        czyWszystkie = new JCheckBox();

        layout.setHorizontalGroup(
                layout.createParallelGroup()
                .addComponent(scrollPane)
                .addGroup(layout.createSequentialGroup()
                    .addComponent(dodaj)
//                    .addComponent(usun)
//                    .addComponent(zmienNazwe)
                    )
                .addGroup(layout.createSequentialGroup()
                    .addComponent(edytujPracownikow)
                    .addComponent(edytujUmiejetnosci))
                .addGroup(layout.createSequentialGroup()
                    .addComponent(wszyscy)
                    .addComponent(czyWszystkie)));

        layout.setVerticalGroup(
                layout.createSequentialGroup()
                .addComponent(scrollPane)
                .addGroup(layout.createParallelGroup()
                    .addComponent(dodaj)
//                    .addComponent(usun)
//                    .addComponent(zmienNazwe)
                    )
                .addGroup(layout.createParallelGroup()
                    .addComponent(edytujPracownikow)
                    .addComponent(edytujUmiejetnosci))
                .addGroup(layout.createParallelGroup()
                    .addComponent(wszyscy)
                    .addComponent(czyWszystkie)));

        dodaj.addActionListener(this);
        edytujPracownikow.addActionListener(this);
        edytujUmiejetnosci.addActionListener(this);
        czyWszystkie.addActionListener(this);
    }

    void setZadania(ArrayList<Zadanie> zadania) {
        listaZadan.setListData(zadania.toArray());
    }
    
    public void actionPerformed(ActionEvent e) {
        if(e.getSource() == dodaj){
            dodaj();
	}
        else if(e.getSource() == edytujPracownikow){
            if(listaZadan.isSelectionEmpty()) {
        	komunikujBlad();
            }
            else {
                edytujPracownikow();
            }
        }
        else if(e.getSource() == edytujUmiejetnosci){
            if(listaZadan.isSelectionEmpty()) {
        	komunikujBlad();
            }
            else {
        	edytujUmiejetnosci();
            }
        }
        else if(e.getSource() == czyWszystkie) {
            czyWszyscyChanged();
        }
    }

    private void komunikujBlad() {
	JOptionPane.showMessageDialog(this,
		    "Musisz zaznaczyć jedno zadanie!",
		    "Zaznacz zadanie",
		    JOptionPane.WARNING_MESSAGE);
    }

    private void dodaj() {
        final JFrame frame = new JFrame("Nazwa zadania:");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setLayout(new FlowLayout());
        final JTextField field = new JTextField(20);
        frame.add(field);
        JButton akceptuj = new JButton("OK");
        frame.add(akceptuj);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

	    akceptuj.addActionListener(new ActionListener() {

		public void actionPerformed(ActionEvent e) {
		    OWLNamedIndividual ind = Ontology.getFactory()
			    .getOWLNamedIndividual(
				    IRI.create(Ontology.getOwlString() + "#" +
					    field.getText()));

		    List<OWLOntologyChange> oc = new ArrayList<OWLOntologyChange>();

		    OWLClass klasaZadan = Ontology.getFactory()
			    .getOWLClass(
				    IRI.create(Ontology.getOwlString()
					    + "#Zadanie"));
		    OWLAxiom axiom = Ontology.getFactory()
			    .getOWLClassAssertionAxiom(klasaZadan, ind);
		    oc.addAll(Ontology.getManager().addAxiom(
			    Ontology.getOntology(), axiom));

		    Ontology.getManager().applyChanges(oc);
		    Ontology.reload();
		    parent.update();

		    frame.dispose();
		}
	    });
    }
    
    private void edytujPracownikow() {
	final Zadanie zadanie = (Zadanie) listaZadan.getSelectedValue();
	final OWLObjectProperty wykonywal = Ontology.getFactory().getOWLObjectProperty(
		IRI.create(Ontology.getOwlString() + "#wykonywal"));
	    
        final JFrame frame = new JFrame("Kto wykonywał to zadanie?:");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.PAGE_AXIS));
        
        ArrayList<Pracownik> pracownicy = Ontology.getPracownicy();
        final ArrayList<PanelWyboruRol> panele = new ArrayList<PanelWyboruRol>();
        
        for(Pracownik u : pracownicy) {
            PanelWyboruRol panelWyboru = new PanelWyboruRol(u); 
            panele.add(panelWyboru);
            frame.add(panelWyboru);
            panelWyboru.setAlignmentX(LEFT_ALIGNMENT);
            
            try {
        	Set<OWLObjectPropertyAssertionAxiom> pozytywy = Ontology.getOntology()
        		.getObjectPropertyAssertionAxioms(u.getIndywidulum());
                OWLObjectPropertyAssertionAxiom tenKonkretnyPozytyw = Ontology.getFactory()
        		.getOWLObjectPropertyAssertionAxiom(
        			wykonywal, u.getIndywidulum(), zadanie.getIndywidulum());
                if(pozytywy.contains(tenKonkretnyPozytyw)) {
                    panelWyboru.setState(1);
                }
                Set<OWLNegativeObjectPropertyAssertionAxiom> negatywy = Ontology.getOntology()
                	.getNegativeObjectPropertyAssertionAxioms(u.getIndywidulum());
                OWLNegativeObjectPropertyAssertionAxiom tenKonkretnyNegatyw = Ontology.getFactory()
                	.getOWLNegativeObjectPropertyAssertionAxiom(
                		wykonywal, u.getIndywidulum(), zadanie.getIndywidulum());
                    
                if(negatywy.contains(tenKonkretnyNegatyw))
                    panelWyboru.setState(-1);
            }
            catch(Exception ex) {
        	ex.printStackTrace();
            }
            
        }
        
        JButton akceptuj = new JButton("OK");
        frame.add(akceptuj);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

	    akceptuj.addActionListener(new ActionListener() {

		public void actionPerformed(ActionEvent e) {

	            List<OWLOntologyChange> oc = new ArrayList<OWLOntologyChange>();
		    
		    for(int i = 0 ; i < panele.size() ; i++) {
			PanelWyboruRol panel = panele.get(i);
			Pracownik pracownik = (Pracownik) panele.get(i).getKoncept();
			if(panel.getState() == 1) {
			    // Wiemy, że wykonywał
			    OWLAxiom negaxiom = Ontology.getFactory().getOWLNegativeObjectPropertyAssertionAxiom(
				    wykonywal, pracownik.getIndywidulum(), zadanie.getIndywidulum());

			    oc.addAll(Ontology.getManager().removeAxiom(Ontology.getOntology(), negaxiom));

			    OWLAxiom axiom = Ontology.getFactory().getOWLObjectPropertyAssertionAxiom(
				    wykonywal, pracownik.getIndywidulum(), zadanie.getIndywidulum());

			    oc.addAll(Ontology.getManager().addAxiom(Ontology.getOntology(), axiom));
			}
			else if(panel.getState() == 0) {
			    // nie wiemy, czy wykonywal
			    OWLAxiom negaxiom = Ontology.getFactory().getOWLNegativeObjectPropertyAssertionAxiom(
				    wykonywal, pracownik.getIndywidulum(), zadanie.getIndywidulum());

			    oc.addAll(Ontology.getManager().removeAxiom(Ontology.getOntology(), negaxiom));
			    
			    OWLAxiom axiom = Ontology.getFactory().getOWLObjectPropertyAssertionAxiom(
				    wykonywal, pracownik.getIndywidulum(), zadanie.getIndywidulum());

			    oc.addAll(Ontology.getManager().removeAxiom(Ontology.getOntology(), axiom));
			}
			else if(panel.getState() == -1) {
			    // Wiemy, że nie wykonywał
			    OWLAxiom axiom = Ontology.getFactory().getOWLObjectPropertyAssertionAxiom(
				    wykonywal, pracownik.getIndywidulum(), zadanie.getIndywidulum());

			    oc.addAll(Ontology.getManager().removeAxiom(Ontology.getOntology(), axiom));

			    OWLAxiom negaxiom = Ontology.getFactory().getOWLNegativeObjectPropertyAssertionAxiom(
				    wykonywal, pracownik.getIndywidulum(), zadanie.getIndywidulum());

			    oc.addAll(Ontology.getManager().addAxiom(Ontology.getOntology(), negaxiom));
			}
			
		    }
		    
		    try {
			Ontology.getManager().applyChanges(oc);
			Ontology.reload();
			parent.update();
		    } catch (Exception ex) {
			ex.printStackTrace();
		    }

		    frame.dispose();
		}
	    });
    }
    
    private void edytujUmiejetnosci() {
	final Zadanie zadanie = (Zadanie) listaZadan.getSelectedValue();
	final OWLObjectProperty jestWymaganaPrzez = Ontology.getFactory().getOWLObjectProperty(
		IRI.create(Ontology.getOwlString() + "#jestWymaganaPrzez"));
	    
        final JFrame frame = new JFrame("Jakich umiejętności wymaga to zadanie?:");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.PAGE_AXIS));
        
        ArrayList<Umiejetnosc> umiejetnosci = Ontology.getUmiejetnosci();
        final ArrayList<PanelWyboruRol> panele = new ArrayList<PanelWyboruRol>();
        
        for(Umiejetnosc u : umiejetnosci) {
            PanelWyboruRol panelWyboru = new PanelWyboruRol(u); 
            panele.add(panelWyboru);
            frame.add(panelWyboru);
            panelWyboru.setAlignmentX(LEFT_ALIGNMENT);
            
            try {
        	Set<OWLObjectPropertyAssertionAxiom> pozytywy = Ontology.getOntology()
        		.getObjectPropertyAssertionAxioms(u.getIndywidulum());
                OWLObjectPropertyAssertionAxiom tenKonkretnyPozytyw = Ontology.getFactory()
        		.getOWLObjectPropertyAssertionAxiom(
        			jestWymaganaPrzez, u.getIndywidulum(), zadanie.getIndywidulum());
                if(pozytywy.contains(tenKonkretnyPozytyw)) {
                    panelWyboru.setState(1);
                }
                Set<OWLNegativeObjectPropertyAssertionAxiom> negatywy = Ontology.getOntology()
                	.getNegativeObjectPropertyAssertionAxioms(u.getIndywidulum());
                OWLNegativeObjectPropertyAssertionAxiom tenKonkretnyNegatyw = Ontology.getFactory()
                	.getOWLNegativeObjectPropertyAssertionAxiom(
                		jestWymaganaPrzez, u.getIndywidulum(), zadanie.getIndywidulum());
                    
                if(negatywy.contains(tenKonkretnyNegatyw))
                    panelWyboru.setState(-1);
            }
            catch(Exception ex) {
        	ex.printStackTrace();
            }
            
        }
        
        JButton akceptuj = new JButton("OK");
        frame.add(akceptuj);
        frame.pack();
        frame.setLocationRelativeTo(null);
	frame.setVisible(true);

	akceptuj.addActionListener(new ActionListener() {

	    public void actionPerformed(ActionEvent e) {

		List<OWLOntologyChange> oc = new ArrayList<OWLOntologyChange>();

		for (int i = 0; i < panele.size(); i++) {
		    PanelWyboruRol panel = panele.get(i);
		    Umiejetnosc umiejetnosc = (Umiejetnosc) panele.get(i)
			    .getKoncept();
		    if (panel.getState() == 1) {
			// Wiemy, że wymaga
			OWLAxiom negaxiom = Ontology.getFactory()
				.getOWLNegativeObjectPropertyAssertionAxiom(
					jestWymaganaPrzez,
					umiejetnosc.getIndywidulum(),
					zadanie.getIndywidulum());

			oc.addAll(Ontology.getManager().removeAxiom(
				Ontology.getOntology(), negaxiom));

			OWLAxiom axiom = Ontology.getFactory()
				.getOWLObjectPropertyAssertionAxiom(
					jestWymaganaPrzez,
					umiejetnosc.getIndywidulum(),
					zadanie.getIndywidulum());

			oc.addAll(Ontology.getManager().addAxiom(
				Ontology.getOntology(), axiom));
		    } else if (panel.getState() == 0) {
			// nie wiemy, czy wymaga
			OWLAxiom negaxiom = Ontology.getFactory()
				.getOWLNegativeObjectPropertyAssertionAxiom(
					jestWymaganaPrzez,
					umiejetnosc.getIndywidulum(),
					zadanie.getIndywidulum());

			oc.addAll(Ontology.getManager().removeAxiom(
				Ontology.getOntology(), negaxiom));

			OWLAxiom axiom = Ontology.getFactory()
				.getOWLObjectPropertyAssertionAxiom(
					jestWymaganaPrzez,
					umiejetnosc.getIndywidulum(),
					zadanie.getIndywidulum());

			oc.addAll(Ontology.getManager().removeAxiom(
				Ontology.getOntology(), axiom));
		    } else if (panel.getState() == -1) {
			// Wiemy, że nie wymaga
			OWLAxiom axiom = Ontology.getFactory()
				.getOWLObjectPropertyAssertionAxiom(
					jestWymaganaPrzez,
					umiejetnosc.getIndywidulum(),
					zadanie.getIndywidulum());

			oc.addAll(Ontology.getManager().removeAxiom(
				Ontology.getOntology(), axiom));

			OWLAxiom negaxiom = Ontology.getFactory()
				.getOWLNegativeObjectPropertyAssertionAxiom(
					jestWymaganaPrzez,
					umiejetnosc.getIndywidulum(),
					zadanie.getIndywidulum());

			oc.addAll(Ontology.getManager().addAxiom(
				Ontology.getOntology(), negaxiom));
		    }

		}

		// pobranie zestawu umiejętności, które są wymagane przez to zadanie
		OWLObjectProperty wymagaUmiejetnosci = Ontology
			.getFactory()
			.getOWLObjectProperty(
				IRI.create(Ontology.getOwlString() + "#wymaga"));

		OWLNamedIndividual zadanie = ((Zadanie) listaZadan
			.getSelectedValue()).getIndywidulum();
		Set<OWLNamedIndividual> umiejetnosci = Ontology.getReasoner()
			.getObjectPropertyValues(zadanie, wymagaUmiejetnosci)
			.getFlattened();
		
		for (OWLNamedIndividual ind : umiejetnosci) {

		    // wygenerowanie nazwy nowego konceptu, który określa
		    // zadania wymagające, aby wykonywał je co najmniej jeden
		    // pracownik
		    // posiadający wymaganą umiejętność

		    String zURLem = ind.toString();
		    String bezURLa = zURLem.substring(zURLem.indexOf('#') + 1,
			    zURLem.length() - 1);

		    // utworzenie tego konceptu
		    OWLClass zadanieWymagajaceUmiejetnosci = Ontology
			    .getFactory().getOWLClass(
				    IRI.create(Ontology.getOwlString()
					    + "#zadanieWymagajaceUmiejetnosci"
					    + bezURLa));

		    OWLAxiom zadanieJestTejKlasy = Ontology.getFactory()
			    .getOWLClassAssertionAxiom(
				    zadanieWymagajaceUmiejetnosci, zadanie);

		    oc.addAll(Ontology.getManager().addAxiom(
			    Ontology.getOntology(), zadanieJestTejKlasy));

		    // jest on podkonceptem zadania wykonywanego
		    OWLClass zadanieWykonywane = Ontology.getFactory()
			    .getOWLClass(
				    IRI.create(Ontology.getOwlString()
					    + "#ZadanieWykonywane"));

		    OWLAxiom zadanieWymagajaceJestWykonywane = Ontology
			    .getFactory().getOWLSubClassOfAxiom(
				    zadanieWymagajaceUmiejetnosci,
				    zadanieWykonywane);

		    oc.addAll(Ontology.getManager().addAxiom(
			    Ontology.getOntology(),
			    zadanieWymagajaceJestWykonywane));

		    // zadanie było wykonywane przez pracowników, którzy mają
		    // umiejętność

		    OWLObjectProperty byloWykonywane = Ontology.getFactory()
			    .getOWLObjectProperty(
				    IRI.create(Ontology.getOwlString()
					    + "#byloWykonywane"));

		    OWLObjectProperty maUmiejetnosc = Ontology.getFactory()
			    .getOWLObjectProperty(
				    IRI.create(Ontology.getOwlString()
					    + "#maUmiejetnosc"));

		    Set<OWLIndividual> umiejetnosciOWL = new HashSet<OWLIndividual>();
		    umiejetnosciOWL.add(ind);

		    OWLObjectOneOf set = Ontology.getFactory().getOWLObjectOneOf(umiejetnosciOWL);

		    OWLObjectSomeValuesFrom pracownicyPosiadajacyUmiejetnosc = Ontology
			    .getFactory().getOWLObjectSomeValuesFrom(
				    maUmiejetnosc, set);

		    OWLObjectSomeValuesFrom zadaniaWykonywanePrzezPracownikowPosiadajacychUmiejetnosc = Ontology
			    .getFactory().getOWLObjectSomeValuesFrom(
				    byloWykonywane, pracownicyPosiadajacyUmiejetnosc);

		    OWLAxiom axiom = Ontology
			    .getFactory()
			    .getOWLSubClassOfAxiom(
				    zadanieWymagajaceUmiejetnosci, zadaniaWykonywanePrzezPracownikowPosiadajacychUmiejetnosc);
		    
		    oc.addAll(Ontology.getManager().addAxiom(
			    Ontology.getOntology(), axiom));
		}

		try {
		    Ontology.getManager().applyChanges(oc);
		    Ontology.reload();
		    parent.update();
		} catch (Exception ex) {
		    ex.printStackTrace();
		}

		frame.dispose();
	    }
	});
    }
    
    public void czyWszyscyChanged() {

	List<OWLOntologyChange> oc = new ArrayList<OWLOntologyChange>();

	OWLClass klasaZadaniowa = Ontology.getFactory()
		.getOWLClass(
			IRI.create(Ontology.getOwlString()
				+ "#Zadanie"));

	if(czyWszystkie.isSelected()) {
	    ArrayList<Zadanie> zadania = Ontology.getZadania();
	    Set<OWLIndividual> zadaniaOWL = new HashSet<OWLIndividual>();
	    for(Zadanie z : zadania)
		zadaniaOWL.add(z.getIndywidulum());

	    OWLObjectOneOf set = Ontology.getFactory().getOWLObjectOneOf(zadaniaOWL);

	    OWLAxiom eqaxiom = Ontology.getFactory().getOWLEquivalentClassesAxiom(
		    klasaZadaniowa,	set);

	    oc.addAll(Ontology.getManager().addAxiom(Ontology.getOntology(), eqaxiom));
	}
	else {
	    Set<OWLEquivalentClassesAxiom> eqaxioms = Ontology.getOntology().getEquivalentClassesAxioms(klasaZadaniowa);

	    oc.addAll(Ontology.getManager().removeAxioms(Ontology.getOntology(), eqaxioms));
	}

	try {
	    Ontology.getManager().applyChanges(oc);
	    Ontology.reload();
	    parent.update();
	} catch (Exception ex) {
	    ex.printStackTrace();
	}
    }
}
